Skip to content

feat(kernel): query-tags parity + Thrift-parity OAuth (scopes/routing/U2M id) + no-op unsupported options + KERNEL_REV bump#430

Merged
msrathore-db merged 5 commits into
mainfrom
msrathore/sea-query-tags-wiring
Jun 10, 2026
Merged

feat(kernel): query-tags parity + Thrift-parity OAuth (scopes/routing/U2M id) + no-op unsupported options + KERNEL_REV bump#430
msrathore-db merged 5 commits into
mainfrom
msrathore/sea-query-tags-wiring

Conversation

@msrathore-db

@msrathore-db msrathore-db commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Two kernel-backend auth/session fixes (rebased onto the post-#428 lib/kernel path).

1. Session-level query tags (KernelBackend.openSession)

Serializes request.queryTags into the reserved QUERY_TAGS session conf, which the kernel allowlists (SESSION_CONF_ALLOWLIST) and forwards onto the SEA CreateSession session_confs — mirroring ThriftBackend.openSession. queryTags takes precedence over an explicit configuration.QUERY_TAGS.

Verified end-to-end against a live warehouse: the tag lands in system.query.history.query_tags.

Note: this PR is session-level only. Statement-level per-query tags (executeStatement(sql, { queryTags })) are dropped by the current kernel (the SEA execute wire request has no per-statement conf field) — that needs kernel #150 (feat(sea): send per-statement query tags on the wire), which I built + verified separately. Until #150 merges and KERNEL_REV bumps, statement-level tags are a no-op on the kernel path.

2. Thrift-parity OAuth scopes (configurable via oauthScopes)

The kernel U2M flow passed no scopes, so it fell through to the kernel's bare default all-apis offline_access. The databricks-sql-connector OAuth app is registered for sql, so U2M requested the wrong scope set. Now the driver passes scopes explicitly:

  • U2M → defaults to ['sql', 'offline_access'] (matches the Thrift driver's defaultOAuthScopes).
  • M2M → defaults to ['all-apis'] (matches Thrift + the kernel's M2M default).
  • Both overridable via a new public oauthScopes connect option — closing the configurability gap with pyo3 (which already forwards scopes on M2M).

Driver-only: the napi binding already forwards oauth_scopes, and the kernel's u2m.rs/m2m.rs feed them into the authorize/token request.

Tests

  • tests/unit/kernel/execution.test.ts — session-level queryTagssessionConf.QUERY_TAGS, precedence over configuration.QUERY_TAGS.
  • tests/unit/kernel/auth-u2m.test.ts / auth-m2m.test.ts — default scopes (U2M sql offline_access, M2M all-apis), caller override, empty-array fallback.

All 135 affected unit tests pass locally.

This pull request and its description were written by Isaac.

…ssion

Ports the session-level query-tags wiring onto the post-#428 lib/kernel path
(originally lib/sea/SeaBackend, before the SEA→kernel rename). openSession
serializes request.queryTags into the reserved QUERY_TAGS session conf, which
the kernel allowlists (SESSION_CONF_ALLOWLIST) and forwards onto the SEA
CreateSession session_confs — mirroring ThriftBackend.openSession. queryTags
takes precedence over an explicit configuration.QUERY_TAGS.

Verified end-to-end against a live warehouse: the tag lands in
system.query.history.query_tags.

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
…thScopes

The kernel U2M flow passed no scopes, so it fell through to the kernel's bare
default (all-apis offline_access). The databricks-sql-connector OAuth app is
registered for `sql`, so U2M auth used the wrong scope set. Pass scopes
explicitly from the driver:

  - U2M defaults to ['sql', 'offline_access'] (matches the Thrift driver's
    defaultOAuthScopes), overriding the kernel's all-apis default.
  - M2M defaults to ['all-apis'] (matches Thrift + the kernel's M2M default).
  - Both overridable via a new `oauthScopes` connect option — closing the
    configurability gap with pyo3, which already forwards `scopes` on M2M.

Driver-only change: the napi binding already forwards oauth_scopes and the
kernel's u2m.rs/m2m.rs feed them into the authorize/token request.

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
@msrathore-db msrathore-db force-pushed the msrathore/sea-query-tags-wiring branch from 21d31dd to d6c0d81 Compare June 9, 2026 15:25
@msrathore-db msrathore-db changed the title feat(sea): wire session-level query tags (statement-level already forwarded) feat(kernel): session-level query tags + Thrift-parity OAuth scopes (configurable) Jun 9, 2026
Per-statement options the kernel backend doesn't honour are now NO-OPs (logged
at warn), not HiveDriverErrors, so call sites written for the Thrift backend are
drop-in on the kernel path:

  - useCloudFetch / useLZ4Compression — kernel-governed perf/format hints
  - stagingAllowedLocalPath — staging not yet exposed on the kernel

Ignoring these can't change query results. Parameter binding (compound/BINARY)
is deliberately NOT no-op'd — a dropped param would silently change results, so
it still throws.

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
…tom U2M client id

Make the kernel auth flow selector + client-id resolution byte-for-byte identical
to the Thrift driver (`DBSQLClient.createAuthProvider`):

  - flow     = `oauthClientSecret === undefined ? U2M : M2M`  (strict undefined)
  - clientId = `oauthClientId ?? defaultClientId`             (`??` guards null/undefined only)

No blank/reserved normalization on the OAuth fields — a present-but-degenerate
value (`""` / `"undefined"` / whitespace) is forwarded verbatim, exactly as Thrift
forwards it. This removes every divergence from the Thrift backend across the full
(clientId × clientSecret) input matrix (verified). Consequences vs the prior
id-presence routing:

  - `oauthClientId` + no secret now runs U2M (browser) and forwards the id as a
    custom U2M client (Thrift does the same).
  - M2M with no/blank id no longer throws "id required" — it uses the default
    client (`?? defaultClientId`), matching Thrift.
  - A present-but-empty/`"undefined"` secret routes to M2M (not U2M), matching
    Thrift's strict `=== undefined` check.

Trade-off (accepted for parity): this re-imports Thrift's env-stringification
behaviour — a secret/id env var that resolved to `""`/`"undefined"` is taken
literally rather than treated as unset.

Updated the auth unit tests (u2m/m2m/edge-cases) to assert the strict-parity
matrix.

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
…tags + proxy + UA)

Bump the pinned kernel from b676275 to 34b4c20 (current kernel main), which
brings:
  - #150 — per-statement query tags on the SEA wire (native query_tags array).
    This is what makes `executeStatement(sql, { queryTags })` actually reach the
    server on the kernel path — bringing statement-level query tags to parity
    with the Thrift backend (the driver already serialized them into
    statement_conf["query_tags"]; the kernel previously dropped that before the
    wire). Verified e2e: the tag now lands in system.query.history.query_tags.
  - #129 — programmatic HTTP/HTTPS proxy + per-connection socket timeout
    (additive optional napi ConnectionOptions fields; refreshed in index.d.ts).
  - #151 — caller User-Agent overwrites the kernel base UA for accurate
    query-source attribution.

Refreshes the committed napi types (native/kernel/index.d.ts) accordingly; the
new fields are optional, so no driver-side change is required.

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
@msrathore-db msrathore-db force-pushed the msrathore/sea-query-tags-wiring branch from 677123f to f5bb586 Compare June 10, 2026 11:01
@msrathore-db msrathore-db added this pull request to the merge queue Jun 10, 2026
@msrathore-db msrathore-db changed the title feat(kernel): session-level query tags + Thrift-parity OAuth scopes (configurable) feat(kernel): query-tags parity + Thrift-parity OAuth (scopes/routing/U2M id) + no-op unsupported options + KERNEL_REV bump Jun 10, 2026
Merged via the queue into main with commit 3358a61 Jun 10, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants